#pragma once

#include "item/handle.h"
#include "item/iitemobserver.h"
#include "OldGraphicsView/Palette.h"
#include "xdl/symbol.h"

#include <QGraphicsItem>

class QGraphicsItem;
class QPainter;

namespace SymbolEditor
{

    class GraphicsItem: public QGraphicsItem, public IItemObserver
    {

    public:
        enum { ModelType = UserType + 65536 };

        explicit GraphicsItem(GraphicsItem *parent = nullptr);
        virtual ~GraphicsItem();

        virtual GraphicsItem *clone() = 0;
        int handleCount() const;
        Handle *handleAt(int idx);

        void setLineStyle(LineStyle style);
        LineStyle lineStyle() const;
        void setLineWidth(LineWidth width);
        LineWidth lineWidth() const;
        void setLineColor(Color color);
        Color lineColor() const;
        void setFillStyle(FillStyle style);
        FillStyle fillStyle() const;
        void setFillColor(Color color);
        Color fillColor() const;
        bool isXMirrored() const;
        void setXMirrored(bool mirrored);
        bool isYMirrored() const;
        void setYMirrored(bool mirrored);

        virtual QList<QPointF> hotSpots() const;
        virtual QList<QPointF> endPoints() const;
        virtual QList<QPointF> midPoints() const;
        virtual QList<QPointF> centerPoints() const;
        virtual QList<QPointF> nearestPoints(QPointF pos) const;

        virtual QList<PropertyId> propertyIdList() const;
        virtual void setProperty(PropertyId id, const QVariant &value);
        virtual QVariant property(PropertyId id) const;
        void setProperties(QMap<PropertyId, QVariant> properties);
        QMap<PropertyId, QVariant> properties() const;

        void setPalette(LeGraphicsView::Palette palette);
        LeGraphicsView::Palette palette() const;

    protected:
        static QPointF nearestPoint(const QLineF &line, const QPointF &point);
        static QPointF nearestPoint(const QPointF &center, qreal radius, const QPointF &point);
        static QPointF nearestPoint(const QPointF &center, qreal radius,
                                    qreal startAngle, qreal spanAngle,
                                    const QPointF &point);
        static QPointF nearestPoint(const QList<QPointF> &candidates, const QPointF &point);

        QPen pen() const;
        QBrush brush() const;

        Handle *addHandle(int id, Handle::Role role, Handle::Shape shape,
                          const QPointF &pos = QPointF(0, 0));
        void removeAllHandles();

        void cloneTo(GraphicsItem *dst);

        static QPainterPath shapeFromPath(const QPainterPath &path, const QPen &pen);

        // FIXME: should be private
        mutable QRectF m_boundingRect;
        QMap<Handle *, int> m_handleToId;
        QMap<int, Handle *> m_idToHandle;

    private:
        LeGraphicsView::Palette m_palette;

        LineStyle m_lineStyle;
        LineWidth m_lineWidth;
        Color m_lineColor;
        FillStyle m_fillStyle;
        Color m_fillColor;
        bool m_isXMirrored;
        bool m_isYMirrored;

        void addAbstractHandle(Handle *handle);
        void removeHandle(int id);
        void removeHandle(Handle *handle);
        Handle *handle(int id) const;

        void updateMirroringTransform();

        // QGraphicsItem interface
    public:
        int type() const override { return Type; }
    };

}
